﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;

using BodaNetCommunications.Nodes;
using BodaNetCommunications.NodeSettings;
using BodaNetCommunications.Utilities.ComTypes;

namespace BodaNetCommunications.ModbusTcpComs
{
    public class ModbusTCPVariable : BodaNodeClass, IXmlConvert
    {
        public AlarmEnitity Alarm = new AlarmEnitity();

        public string VarAddress { get; set; }

        public DataType VarType { get; set; }

        public string Type { get; set; }

        public string Scale { get; set; }

        public string Offset { get; set; }

        public object Value { get; set; }

        public BodaReadWrite AccessProperty { get; set; }

        public ModbusTCPVariable()
        {
            Name = "变量";
            Description = "具体的通讯变量地址及类型";
            VarAddress = "0";
            NodeType = 100;
            NodeHead = "Variable";
            Type = "ModbusTCP";
            Scale = "1";
            Offset = "0";
            VarType = DataType.@float;
            AccessProperty = BodaReadWrite.只读;
        }

        public override void LoadByXmlElement(XElement element)
        {
            base.LoadByXmlElement(element);
            Type = element.Attribute("Type").Value;
            VarAddress = element.Attribute("VarAddress").Value;
            VarType = (DataType)Enum.Parse(typeof(DataType), element.Attribute("VarType").Value, ignoreCase: true);
            Scale = element.Attribute("Scale").Value;
            Offset = element.Attribute("Offset").Value;
            AccessProperty = (BodaReadWrite)Enum.Parse(typeof(BodaReadWrite), element.Attribute("AccessProperty").Value, ignoreCase: true);
            Alarm.AlarmEnable = bool.Parse(element.Attribute("AlarmEnable").Value);
            Alarm.ArchiveEnable = bool.Parse(element.Attribute("ArchiveEnable").Value);
            Alarm.SetLimitEnable = bool.Parse(element.Attribute("SetLimitEnable").Value);
            if (Alarm.AlarmEnable)
            {
                Alarm.AlarmType = bool.Parse(element.Attribute("AlarmType").Value);
                Alarm.DiscreteAlarmType = bool.Parse(element.Attribute("DiscreteAlarmType").Value);
                Alarm.DiscreteAlarmPriority = int.Parse(element.Attribute("DiscreteAlarmPriority").Value);
                Alarm.DiscreteAlarmNote = element.Attribute("DiscreteAlarmNote").Value;
                Alarm.LoLoAlarmEnable = bool.Parse(element.Attribute("LoLoAlarmEnable").Value);
                Alarm.LoLoAlarmValue = float.Parse(element.Attribute("LoLoAlarmValue").Value);
                Alarm.LoLoAlarmPriority = int.Parse(element.Attribute("LoLoAlarmPriority").Value);
                Alarm.LoLoAlarmNote = element.Attribute("LoLoAlarmNote").Value;
                Alarm.LowAlarmEnable = bool.Parse(element.Attribute("LowAlarmEnable").Value);
                Alarm.LowAlarmValue = float.Parse(element.Attribute("LowAlarmValue").Value);
                Alarm.LowAlarmPriority = int.Parse(element.Attribute("LowAlarmPriority").Value);
                Alarm.LowAlarmNote = element.Attribute("LowAlarmNote").Value;
                Alarm.HighAlarmEnable = bool.Parse(element.Attribute("HighAlarmEnable").Value);
                Alarm.HighAlarmValue = float.Parse(element.Attribute("HighAlarmValue").Value);
                Alarm.HighAlarmPriority = int.Parse(element.Attribute("HighAlarmPriority").Value);
                Alarm.HighAlarmNote = element.Attribute("HighAlarmNote").Value;
                Alarm.HiHiAlarmEnable = bool.Parse(element.Attribute("HiHiAlarmEnable").Value);
                Alarm.HiHiAlarmValue = float.Parse(element.Attribute("HiHiAlarmValue").Value);
                Alarm.HiHiAlarmPriority = int.Parse(element.Attribute("HiHiAlarmPriority").Value);
                Alarm.HiHiAlarmNote = element.Attribute("HiHiAlarmNote").Value;
            }

            if (Alarm.ArchiveEnable)
            {
                Alarm.ArchivePeriod = int.Parse(element.Attribute("ArchivePeriod").Value);
            }

            if (Alarm.SetLimitEnable)
            {
                Alarm.SetLimitMax = float.Parse(element.Attribute("SetLimitMax").Value);
                Alarm.SetLimitMin = float.Parse(element.Attribute("SetLimitMin").Value);
            }
        }

        public override XElement ToXmlElement()
        {
            XElement xElement = base.ToXmlElement();
            xElement.SetAttributeValue("Type", Type);
            xElement.SetAttributeValue("VarAddress", VarAddress);
            xElement.SetAttributeValue("VarType", VarType);
            xElement.SetAttributeValue("Scale", Scale);
            xElement.SetAttributeValue("Offset", Offset);
            xElement.SetAttributeValue("AccessProperty", AccessProperty);
            xElement.SetAttributeValue("AlarmEnable", Alarm.AlarmEnable.ToString());
            xElement.SetAttributeValue("ArchiveEnable", Alarm.ArchiveEnable.ToString());
            xElement.SetAttributeValue("SetLimitEnable", Alarm.SetLimitEnable.ToString());
            if (Alarm.AlarmEnable)
            {
                xElement.SetAttributeValue("AlarmType", Alarm.AlarmType.ToString());
                xElement.SetAttributeValue("DiscreteAlarmType", Alarm.DiscreteAlarmType.ToString());
                xElement.SetAttributeValue("DiscreteAlarmPriority", Alarm.DiscreteAlarmPriority.ToString());
                xElement.SetAttributeValue("DiscreteAlarmNote", Alarm.DiscreteAlarmNote.ToString());
                xElement.SetAttributeValue("LoLoAlarmEnable", Alarm.LoLoAlarmEnable.ToString());
                xElement.SetAttributeValue("LoLoAlarmValue", Alarm.LoLoAlarmValue.ToString());
                xElement.SetAttributeValue("LoLoAlarmPriority", Alarm.LoLoAlarmPriority.ToString());
                xElement.SetAttributeValue("LoLoAlarmNote", Alarm.LoLoAlarmNote.ToString());
                xElement.SetAttributeValue("LowAlarmEnable", Alarm.LowAlarmEnable.ToString());
                xElement.SetAttributeValue("LowAlarmValue", Alarm.LowAlarmValue.ToString());
                xElement.SetAttributeValue("LowAlarmPriority", Alarm.LowAlarmPriority.ToString());
                xElement.SetAttributeValue("LowAlarmNote", Alarm.LowAlarmNote.ToString());
                xElement.SetAttributeValue("HighAlarmEnable", Alarm.HighAlarmEnable.ToString());
                xElement.SetAttributeValue("HighAlarmValue", Alarm.HighAlarmValue.ToString());
                xElement.SetAttributeValue("HighAlarmPriority", Alarm.HighAlarmPriority.ToString());
                xElement.SetAttributeValue("HighAlarmNote", Alarm.HighAlarmNote.ToString());
                xElement.SetAttributeValue("HiHiAlarmEnable", Alarm.HiHiAlarmEnable.ToString());
                xElement.SetAttributeValue("HiHiAlarmValue", Alarm.HiHiAlarmValue.ToString());
                xElement.SetAttributeValue("HiHiAlarmPriority", Alarm.HiHiAlarmPriority.ToString());
                xElement.SetAttributeValue("HiHiAlarmNote", Alarm.HiHiAlarmNote.ToString());
            }

            if (Alarm.ArchiveEnable)
            {
                xElement.SetAttributeValue("ArchivePeriod", Alarm.ArchivePeriod.ToString());
            }

            if (Alarm.SetLimitEnable)
            {
                xElement.SetAttributeValue("SetLimitEnable", Alarm.SetLimitEnable.ToString());
                xElement.SetAttributeValue("SetLimitMax", Alarm.SetLimitMax.ToString());
                xElement.SetAttributeValue("SetLimitMin", Alarm.SetLimitMin.ToString());
            }

            return xElement;
        }

        public override List<BodaNodeClassRenderItem> GetNodeClassRenders()
        {
            List<BodaNodeClassRenderItem> nodeClassRenders = base.GetNodeClassRenders();
            nodeClassRenders.Add(new BodaNodeClassRenderItem("变量地址", VarAddress));
            nodeClassRenders.Add(new BodaNodeClassRenderItem("变量类型", VarType.ToString()));
            nodeClassRenders.Add(new BodaNodeClassRenderItem("比例系数", Scale.ToString()));
            nodeClassRenders.Add(new BodaNodeClassRenderItem("偏移量", Offset.ToString()));
            nodeClassRenders.Add(new BodaNodeClassRenderItem("读写属性", AccessProperty.ToString()));
            nodeClassRenders.Add(new BodaNodeClassRenderItem("当前数值", Value?.ToString()));
            if (Alarm.AlarmEnable)
            {
                nodeClassRenders.Add(new BodaNodeClassRenderItem("报警启用", Alarm.AlarmEnable ? "启用" : "禁用"));
                nodeClassRenders.Add(new BodaNodeClassRenderItem("报警类型", Alarm.AlarmType ? "条件报警" : "离散报警"));
                if (!Alarm.AlarmType)
                {
                    nodeClassRenders.Add(new BodaNodeClassRenderItem("离散报警类型", Alarm.DiscreteAlarmType ? "上升沿" : "下降沿"));
                    nodeClassRenders.Add(new BodaNodeClassRenderItem("离散报警优先级", Alarm.DiscreteAlarmPriority.ToString()));
                    nodeClassRenders.Add(new BodaNodeClassRenderItem("离散报警说明", Alarm.DiscreteAlarmNote));
                }
                else
                {
                    if (Alarm.LoLoAlarmEnable)
                    {
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("LoLo启用", Alarm.LoLoAlarmEnable ? "启用" : "禁用"));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("LoLo报警值", Alarm.LoLoAlarmValue.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("LoLo优先级", Alarm.LoLoAlarmPriority.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("LoLo报警说明", Alarm.LoLoAlarmNote));
                    }

                    if (Alarm.LowAlarmEnable)
                    {
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("Low启用", Alarm.LowAlarmEnable ? "启用" : "禁用"));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("Low报警值", Alarm.LowAlarmValue.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("Low优先级", Alarm.LowAlarmPriority.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("Low报警说明", Alarm.LowAlarmNote));
                    }

                    if (Alarm.HighAlarmEnable)
                    {
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("High启用", Alarm.HighAlarmEnable ? "启用" : "禁用"));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("High报警值", Alarm.HighAlarmValue.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("High优先级", Alarm.HighAlarmPriority.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("High报警说明", Alarm.HighAlarmNote));
                    }

                    if (Alarm.HiHiAlarmEnable)
                    {
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("HiHi启用", Alarm.HiHiAlarmEnable ? "启用" : "禁用"));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("HiHi报警值", Alarm.HiHiAlarmValue.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("HiHi优先级", Alarm.HiHiAlarmPriority.ToString()));
                        nodeClassRenders.Add(new BodaNodeClassRenderItem("HiHi报警说明", Alarm.HiHiAlarmNote));
                    }
                }
            }

            if (Alarm.ArchiveEnable)
            {
                nodeClassRenders.Add(new BodaNodeClassRenderItem("归档启用", Alarm.ArchiveEnable ? "启用" : "禁用"));
                nodeClassRenders.Add(new BodaNodeClassRenderItem("归档周期", Alarm.ArchivePeriod / 3600 + "小时" + Alarm.ArchivePeriod % 3600 / 60 + "分钟" + Alarm.ArchivePeriod % 60 + "秒"));
            }

            if (Alarm.SetLimitEnable)
            {
                nodeClassRenders.Add(new BodaNodeClassRenderItem("设定限制启用", Alarm.SetLimitEnable ? "启用" : "禁用"));
                nodeClassRenders.Add(new BodaNodeClassRenderItem("设定高限", Alarm.SetLimitMax.ToString()));
                nodeClassRenders.Add(new BodaNodeClassRenderItem("设定低限", Alarm.SetLimitMin.ToString()));
            }

            return nodeClassRenders;
        }
    }
}